package tbs.framework.async.task.container

import tbs.framework.async.container.IAsyncTaskContainer
import tbs.framework.async.container.model.AsyncTaskDetail
import tbs.framework.async.exceptions.RemoveTaskError
import tbs.framework.async.task.IAsyncTask
import tbs.framework.log.ILogger
import tbs.framework.log.annotations.AutoLogger

class HashMapAsyncContainer : IAsyncTaskContainer {
    private val taskMap: MutableMap<String, AsyncTaskDetail> = HashMap<String, AsyncTaskDetail>();

    @AutoLogger
    var containerILogger: ILogger? = null;

    override fun addTask(task: IAsyncTask): IAsyncTaskContainer {
        taskMap.putIfAbsent(task.taskId(), AsyncTaskDetail(task));
        return this;
    }

    override fun removeTask(taskId: String): IAsyncTaskContainer {
        taskMap.getOrDefault(taskId, null)?.let { taskDetail ->
            if (taskDetail.task.isRunning) {
                if (!taskDetail.isCancelable) {
                    throw RemoveTaskError("task:${taskDetail.taskId} is running,please remove it later")
                }
                taskDetail.cancelable.cancel("remove task")
            }
            taskMap.remove(taskId)
        }


        return this;
    }

    override fun clearTask(): IAsyncTaskContainer {
        for (task in taskMap.values) {
            try {
                removeTask(task.taskId)
            } catch (e: RemoveTaskError) {
                containerILogger?.warn("remove task error: ${e.message}")
            } catch (e: Throwable) {
                throw e;
            }
        }
        return this;
    }

    override fun getTaskCount(): Int {
        return taskMap.size
    }

    override fun getTaskDetail(taskId: String): AsyncTaskDetail? {
        return taskMap.getOrDefault(taskId, null)
    }

    override fun tasks(): MutableList<AsyncTaskDetail> {
        return taskMap.values.toMutableList()
    }


}